// scaup - Scala up!
// (c) 2008-2010, Normen Müller, normen.mueller@gmail.com  
// $Id: Util.scala 80 2010-05-13 12:31:58Z normen.mueller $
package scaup.spec

import java.io.File
import java.text.MessageFormat.{format}

import org.specs.matcher.Matcher

import scaup.Views._

/** 
 * @author <a href="mailto:normen.mueller@googlemail.com">Normen M&#xFC;ller</a>
 * @version 0.0.5 */
object Util {
  val TMP = System.getProperty("java.io.tmpdir").toFile
  
  val HOME = System.getProperty("user.home").toFile
  
  def gnudiff(left: File,right: File): String = gnudiff("",left,right)
  
  def gnudiff(ops: String,left: File,right: File): String = {
    val child = 
      if(ops != null && ops.length > 0)
        Runtime.getRuntime().exec(Array[String]("/usr/bin/diff",ops,left.ap,right.ap))
      else Runtime.getRuntime().exec(Array[String]("/usr/bin/diff",left.ap,right.ap))
    val buf = new StringBuilder
    val in = child.getInputStream()
    var int = in.read()
    while(int != -1) {
      buf append int.toChar
      int = in.read()
    }
    in.close()
    buf.toString
  }
  
  def gnupatch(p: File,o: File,n: File) = Runtime.getRuntime().exec(Array[String]("/usr/bin/patch","-i",p.ap,o.ap,"-o",n.ap)).waitFor
}

/** 
 * @author <a href="mailto:normen.mueller@googlemail.com">Normen M&#xFC;ller</a>
 * @version 0.0.5 */
case class matchDOTGraph(actual: dot.Graph) extends Matcher[dot.Graph] {
  def apply(expected: => dot.Graph) =     
    (
      (  actual.strict == expected.strict
      && actual.digraph == expected.digraph
      && actual.id == expected.id
      && equalComponents(actual.statements, expected.statements)        
      ),
      "okMsg",
      format("''{0}'' is not equal to\n''{1}''", actual, expected)
    )
  
  private def equalComponents(actual: Seq[dot.Component], expected: Seq[dot.Component]): Boolean =
    (actual.toList, expected.toList) match {
      case ((dot.Attrs(at,aas@_*)::atl), (dot.Attrs(et,eas@_*)::etl)) =>
        at == et && equalComponents(aas, eas) && equalComponents(atl,etl)
      case ((dot.Attr(ak,av)::atl), ((dot.Attr(ek,ev))::etl)) =>
        ak == ek && av == ev && equalComponents(atl,etl)
      case ((dot.Node(an,aas@_*)::atl), (dot.Node(en, eas@_*)::etl)) =>
        an == en && equalComponents(aas, eas) && equalComponents(atl,etl)
      case ((dot.Edge(aas,al,ar)::atl), (dot.Edge(eas, el, er)::etl))  =>
        equalComponents(aas, eas) && al == el && ar == er && equalComponents(atl,etl)
      case ((dot.Subgraph(aid, as@_*)::atl), (dot.Subgraph(rid, rs@_*)::rtl)) => 
        aid == rid && equalComponents(as, rs) && equalComponents(atl, rtl)
      case (Nil, _::_) => false
      case (_::_, Nil) => false
      case (Nil, Nil)  => true
    }
}
